<template>
  <!-- 甘特图（适合做看板并操作） -->
  <div
    @click="echartsMeetingHandleClick"
    class="w-full h-full bg-[#cccccc7e] flex items-center justify-center"
  >
    <div class="w-[90%] h-[80%] bg-white" id="echartsMeetingId">
      <div v-loading="loading" ref="chartRef" class="w-full h-full" />
    </div>
  </div>
</template>

<script setup lang="ts">
import * as echarts from "echarts";
import { nextTick, onMounted, ref, watch, onBeforeUnmount } from "vue";
import { ElMessage } from "element-plus";
const props = defineProps({
  modelValue: {
    type: Array as any,
    default: () => [] as any,
  },
  timeData: {
    type: String,
    default: "",
  },
  slidingBeganTime: {
    type: String,
    default: "",
  },
  slidingEndTime: {
    type: String,
    default: "",
  },
  slidingId: {
    type: String,
    default: "",
  },
});
const emits = defineEmits([
  "update:slidingBeganTime",
  "update:slidingEndTime",
  "update:slidingId",
]);
const chartRef = ref(null);
let chartInstance: any;
// 初始化日期时间
var baseDate = props.timeData
  ? props.timeData
  : `${new Date().getFullYear()}/${new Date().getMonth() + 1}/${new Date().getDate()}`;
// 初始化数据
let meet = props.modelValue?.length
  ? props.modelValue
  : [
      {
        meetingRoomId: "1815217851233611778",
        meetingRoomName: "会议室1217",
        meetingRoomAddress: "康心药业",
        capacityNum: 10,
        meetingRoomStatus: 0,
        meetingRoomLastUseDate: null,
        meetingFacilities: "[]",
        meetingCardVOList: [
          {
            meetingId: "1815218484636438529",
            meetingName: "平台培训会议",
            meetingStatus: 3,
            meetingStartTm: "2024-07-22 11:30",
            meetingEndTm: "2024-07-22 13:30",
            hostByName: "杨兰",
            procinstExtendId: "9677d69da7244d3bdaadb153a7bb28be",
            createByName: "杨兰",
          },
        ],
      },
      {
        meetingRoomId: "1759506209422622722",
        meetingRoomName: "康心药业基地会议室",
        meetingRoomAddress: "贵阳市乌当区高新路16号1712室",
        capacityNum: 12,
        meetingRoomStatus: 0,
        meetingRoomLastUseDate: null,
        meetingFacilities:
          '[{"sort":1,"materialName":"会议黑板（小）","number":1,"materialId":"1759500000237895681"},{"sort":2,"materialName":"会议黑板（大）","number":1,"materialId":"1759499923343720449"},{"sort":3,"materialName":"USB无线遥控笔","number":1,"materialId":"1759497037851312130"},{"sort":4,"materialName":"音响","number":1,"materialId":"1759496920578572289"},{"sort":5,"materialName":"麦克风","number":1,"materialId":"1759496876462882817"}]',
        meetingCardVOList: [
          {
            meetingId: "1815215377475063810",
            meetingName: "评审会议",
            meetingStatus: 3,
            meetingStartTm: "2024-07-22 11:00",
            meetingEndTm: "2024-07-22 13:00",
            hostByName: null,
            procinstExtendId: "d894badd1b54843ce7eb75e762077716",
            createByName: "杨兰",
          },
        ],
      },
    ];
// 处理初始化数据,并为每一个图表小格子注入Y轴对应索引和X轴对应开始和结束时间(注意处理临界值问题导致格子无法选中)
let rangderData = () => {
  let _yDAta: any = [];
  let _xDAta: any = [];
  let meetingData: any = [];
  meet?.forEach((e: any, i: any) => {
    _yDAta.push([e.meetingRoomId, e.meetingRoomName]);
    e.meetingCardVOList?.forEach((m: any) => {
      let meetingValue = [] as any;
      meetingValue[0] = i;
      meetingValue[1] = m.meetingStartTm;
      meetingValue[2] = m.meetingEndTm;
      meetingValue[3] = m.meetingStatus;
      meetingValue[4] = m.meetingId;
      meetingValue[5] = m.meetingName;
      meetingValue[6] = m.hostByName;
      meetingValue[7] = m.procinstExtendId;
      meetingValue[8] = m.createByName;
      meetingData.push(meetingValue);
    });
  });
  let lang = _yDAta?.length;
  for (let index = 0; index < lang; index++) {
    for (let hour = 0; hour < 24; hour++) {
      for (let minute = 0; minute < 60; minute += 15) {
        let startTime = `${hour.toString().padStart(2, "0")}:${minute
          .toString()
          .padStart(2, "0")}`;

        // 计算结束时间，注意处理分钟数进位到下一小时的情况
        let endTimeMinutes = minute + 15;
        let endTimeHour = hour;
        let endTimeMinutesFormatted;
        // 处理临界值问题导致格子无法选中
        if (endTimeMinutes >= 60) {
          endTimeHour += Math.floor(endTimeMinutes / 60);
          endTimeMinutesFormatted = endTimeMinutes % 60;
        } else {
          endTimeMinutesFormatted = endTimeMinutes;
        }

        let endTime = `${endTimeHour
          .toString()
          .padStart(2, "0")}:${endTimeMinutesFormatted.toString().padStart(2, "0")}`;
        _xDAta.push({
          value: [index, baseDate + ` ${startTime}`, baseDate + ` ${endTime}`],
        });
      }
    }
  }
  nextTick(() => {
    let _dataX = JSON.parse(JSON.stringify(_xDAta));
    _dataX?.forEach((element: any, index: number) => {
      meetingData?.forEach((m: any) => {
        if (element.value?.[0] == m?.[0]) {
          let stdt = new Date(m?.[1]);
          let etdt = new Date(m?.[2]);
          let stdtdataX = new Date(element.value?.[1]);
          let etdtdataX = new Date(element.value?.[2]);
          if (stdtdataX >= stdt && etdtdataX <= etdt) {
            let obj = {
              value: m,
            };
            _xDAta?.splice(index, 1, obj);
          }
        }
      });
    });
    reservationsDataX = JSON.parse(JSON.stringify(_xDAta));
    console.log(reservationsDataX, "fdsafdsf");
  });
  console.log(_yDAta, _xDAta, meetingData, "params");
  return {
    _yDAta,
    _xDAta,
  };
};
let loading = false;
// echart配置
var options: any = {
  color: "#0A8BFF",
  backgroundColor: "#fff",
  tooltip: {
    enterable: true,
    hideDelay: 100,
    backgroundColor: "rgba(255,255,255,1)", //背景颜色（此时为默认色）
    borderRadius: 5, //边框圆角
    padding: [5, 0, 5, 0], // [5, 10, 15, 20] 内边距
    textStyle: {
      color: "#000",
    },
    position: function (point: any, params: any, dom: any, rect: any, size: any) {
      if (params.value[3] == 6) {
        dom.innerHTML = `<span>${Controller.stdtTime}</span>--<span>${Controller.etdtTime}</span>`;
        return;
      }
      if (!params.value[4]) {
        dom.style.display = "none";
        return;
      }
      dom.innerHTML = `
              <div style='background-color: #e6e6fe;padding: 10px;color: #101010;font-size:12px;'>
                      <p style='display: flex;'>
                        <span>会议状态：</span>
                        <span>
                        ${
                          params.value[3] == 0
                            ? "待开始"
                            : params.value[3] == 1
                            ? "已开始"
                            : params.value[3] == 2
                            ? "审批中"
                            : "已结束"
                        }
                        </span>
                      </p>
                      <p style='display: flex;'>
                        <span>会议名称：</span>
                        <span>${params.value[5]}</span>
                      </p>
                      <p style='display: flex;'>
                        <span>申请人：</span>
                        <span>${params.value[8]}</span>
                      </p>
                      <p style='display: flex;'>
                        <span>主持人：</span>
                        <span>${params.value[6] ? params.value[6] : "无"}</span>
                      </p>
                      <p style='display: flex;'>
                        <span>开始时间：</span>
                        <span>${params.value[1]}</span>
                      </p>
                      <p style='display: flex;'>
                        <span>结束时间：</span>
                        <span>${params.value[2]}</span>
                      </p>
                    </div>
              `;
    },
  },
  grid: {
    //绘图网格
    left: "2%",
    right: "2%",
    top: "2%",
    bottom: "2%",
    containLabel: true,
  },
  // 底部滚动条
  // dataZoom: [
  //   {
  //     type: "slider",
  //     show: true,
  //     realtime: true,
  //     start: 35,
  //     end: 77,
  //   },
  // ],
  xAxis: {
    type: "time",
    position: "top",
    interval: 3600 * 1000, //以一个小时递增
    max: baseDate + ` 24:00`,
    min: baseDate + ` 00:00`, //将data里最小时间的整点时间设为min,否则min会以data里面的min为开始进行整点递增
    axisLabel: {
      formatter: function (value: any, index: any) {
        var data = new Date(value);
        var hours = data.getHours();
        return hours;
      },
      textStyle: {
        color: "rgba(0,0,0,0.65)", //更改坐标轴文字颜色
        fontSize: 14, //更改坐标轴文字大小
      },
    },
    axisLine: {
      lineStyle: {
        color: "rgba(0,0,0,0.1)",
      },
    },
    // 函数绘图中使用次刻度线
    minorTick: {
      show: true,
      splitNumber: 4,
      lineStyle: {
        color: "#E0E6F1",
        width: 1,
        type: "solid",
      },
    },
    // 显示次刻度线条配置
    minorSplitLine: {
      show: true,
    },
  },
  yAxis: {
    axisLine: {
      show: true,
      lineStyle: {
        color: "rgba(0,0,0,0.1)",
      },
    },
    splitLine: {
      show: true,
      lineStyle: {
        color: "#E0E6F1",
      },
    },
    data: [],
    axisLabel: {
      textStyle: {
        color: "rgba(0, 0, 0, 0.65)", //刻度颜色
        fontSize: 14, //刻度大小
      },
      formatter: function (value: any) {
        return value.split(",")[1];
      },
      // 设置坐标线
      splitLine: {
        show: true,
        lineStyle: {
          color: "#E0E6F1",
          width: 1,
          type: "solid",
        },
      },
    },
  },
  series: [
    {
      type: "custom",
      renderItem: function (params: any, api: any) {
        //开发者自定义的图形元素渲染逻辑，是通过书写 renderItem 函数实现的
        var categoryIndex = api.value(0); //这里使用 api.value(0) 取出当前 dataItem 中第一个维度的数值。
        var start = api.coord([api.value(1), categoryIndex]); // 这里使用 api.coord(...) 将数值在当前坐标系中转换成为屏幕上的点的像素值。
        var end = api.coord([api.value(2), categoryIndex]);
        var startH = api.coord([categoryIndex, 0]);
        var endH = api.coord([categoryIndex, 1]);
        var height = Math.abs(startH[1]) - Math.abs(endH[1]); //注意负数情况导致没有高度问题哦
        height = height && height > 0 ? height : 60;
        return {
          type: "rect", // 表示这个图形元素是矩形。还可以是 'circle', 'sector', 'polygon' 等等。
          shape: echarts.graphic.clipRectByRect(
            {
              // 矩形的位置和大小。
              x: start[0],
              y: start[1] - height / 2,
              width: end[0] - start[0],
              height: height,
            },
            {
              // 当前坐标系的包围盒。
              x: params.coordSys.x,
              y: params.coordSys.y,
              width: params.coordSys.width,
              height: params.coordSys.height,
            }
          ),
          style: api.style(),
        };
      },
      encode: {
        x: [1, 2], // data 中『维度1』和『维度2』对应到 X 轴
        y: 0, // data 中『维度0』对应到 Y 轴
      },
      itemStyle: {
        normal: {
          color: function (params: any) {
            if (params?.value?.length) {
              if (params?.value?.[4]) {
                switch (params?.value?.[3]) {
                  case 0:
                    return "#A6F235";
                  case 1:
                    return "#8083F6";
                  case 2:
                    return "#F23B19";
                  case 3:
                    return "#8A8A8A";
                  default:
                    return "transparent";
                }
              } else if (!params?.value?.[4] && params?.value?.[3] == 6) {
                return "#F5600A";
              } else {
                return "transparent";
              }
            }
          },
        },
      },
      data: [],
    },
  ],
};
// 页面大小改变重绘
const resizeChart = () => {
  chartInstance.resize();
};
// 保存初始化会议的数据
let reservationsDataX = [] as any;
let Controller: any = {
  slidingNum: 0, //点击次数
  slidingBegan: [] as any, //记录第一次点击数据
  slidingEnd: [] as any, //记录第二次点击数据
  slidingIdY: "", //记录当前点击的会议室id
  stdtTime: "",
  etdtTime: "",
  // 点击事件点击一次还是两次进行逻辑处理
  select: function (params: any) {
    if (params?.value?.length > 3) return;
    if (Controller.slidingNum === 0) {
      Controller.slidingBegan = params.value;
      Controller.slidingIdY = params.name?.split(",")[0];
      Controller.slidingNum += 1;
      selectDataEvent(params, Controller.slidingNum);
    } else if (Controller.slidingNum === 1) {
      Controller.slidingEnd = params.value;
      Controller.slidingNum += 1;
      selectDataEvent(params, Controller.slidingNum);
    } else {
      options.series[0].data = JSON.parse(JSON.stringify(reservationsDataX));
      Controller.slidingBegan = params.value;
      Controller.slidingEnd = [];
      Controller.slidingNum = 1;
      selectDataEvent(params, Controller.slidingNum);
    }
  },
};
// 对选择的数据进行渲染处理，并导出选择的会议室id和开始与结束时间
function selectDataEvent(params: any, num: number) {
  console.log(params, num, Controller.slidingBegan, Controller.slidingEnd);
  let stdt: any = "";
  let etdt: any = "";
  if (num == 1) {
    stdt = Controller.slidingBegan?.[1];
    etdt = Controller.slidingBegan?.[2];
  }
  if (num == 2) {
    if (Controller.slidingBegan?.[0] == Controller.slidingEnd?.[0]) {
      let _stdt = new Date(Controller.slidingBegan?.[1]);
      let _etdt = new Date(Controller.slidingEnd?.[2]);
      if (_stdt <= _etdt) {
        stdt = Controller.slidingBegan?.[1];
        etdt = Controller.slidingEnd?.[2];
      } else {
        stdt = Controller.slidingEnd?.[1];
        etdt = Controller.slidingBegan?.[2];
      }
    } else {
      ElMessage.warning("只能选择一个会议室发起会议！");
      emptiedData();
      return;
    }
  }
  options.series?.[0].data?.forEach((element: any, index: any) => {
    let stdtdataX = new Date(element.value?.[1]);
    let etdtdataX = new Date(element.value?.[2]);
    let _stdtdataLiat: any = [];
    if (stdtdataX >= new Date(stdt) && etdtdataX <= new Date(etdt)) {
      if (element.value?.[0] == Controller.slidingBegan?.[0]) {
        let _node: any = [];
        _node[0] = element.value?.[0];
        _node[1] = element.value?.[1];
        _node[2] = element.value?.[2];
        _node[3] = 6;
        _stdtdataLiat.push(_node);
        _stdtdataLiat.forEach((m: any) => {
          if (element.value?.[0] == m?.[0]) {
            let stdt = new Date(m?.[1]);
            let etdt = new Date(m?.[2]);
            let stdtdataX = new Date(element.value?.[1]);
            let etdtdataX = new Date(element.value?.[2]);
            if (stdtdataX >= stdt && etdtdataX <= etdt) {
              options.series?.[0].data?.splice(index, 1, m);
            }
          }
        });
      }
    }
  });
  chartInstance.setOption(options);
  Controller.stdtTime = stdt;
  Controller.etdtTime = etdt;
  emits("update:slidingId", Controller.slidingIdY);
  emits("update:slidingBeganTime", stdt);
  emits("update:slidingEndTime", etdt);
  console.log(Controller.slidingIdY, stdt, etdt, "选择的会议室id和开始时间和结束时间");
}
// 清空选择的数据，重置为初始数据
function emptiedData() {
  options.series[0].data = JSON.parse(JSON.stringify(reservationsDataX));
  chartInstance.setOption(options);
  Controller.slidingNum = 0;
  Controller.slidingBegan = [];
  Controller.slidingEnd = [];
  Controller.slidingIdY = "";
}
// 点击图表选择数据
const handelClick = (params: any) => {
  Controller.select(params);
};
// 初始化数据渲染
function setData() {
  chartInstance = echarts.init(chartRef.value);
  nextTick(() => {
    loading = true;
    let { _yDAta, _xDAta } = rangderData();
    options.yAxis.data = _yDAta;
    options.series[0].data = _xDAta;
    nextTick(() => {
      setOptions(options);
      loading = false;
    });
  });
}
// 会议看板点击看板外区域恢复看板
function echartsMeetingHandleClick(event: any) {
  // 检查点击的元素是否为 div 之外的区域
  if (!event.target.closest("#echartsMeetingId")) {
    if (Controller?.slidingIdY) {
      emptiedData();
    }
  }
}
// 监听会议数据
watch(
  () => props.modelValue,
  (n, o) => {
    meet = n;
    setData();
  },
  { deep: true }
);
// 监听当前日期
watch(
  () => props.timeData,
  (n, o) => {
    baseDate = n;
    setData();
  },
  { deep: true }
);
onMounted(() => {
  // 初始化 ECharts 实例
  //   chartInstance = echarts.init(chartRef.value);
  setData();
  window.addEventListener("resize", resizeChart);
});
// 销毁界面大小监听
onBeforeUnmount(() => {
  window.removeEventListener("resize", resizeChart);
});

// 设置图表的配置项和数据
const setOptions = (options: any) => {
  if (chartInstance) {
    chartInstance.setOption(options);
    chartInstance.on("click", handelClick);
  }
};
// 将清空方法暴露出去
defineExpose({
  emptiedData,
  Controller,
});
</script>

<style scoped></style>
